package com.study.chainofresponsibility;

/**
 * 责任链模式
 * 为请求创建了一个接收者对象的链
 *
 * 比如 请求来的时候 我们需要对请求进行过滤 IP合法吗 有没有敏感词 身份是否合规 登录与否 等  只要有一个不合规 立马就中断请求 不让其进入业务
 * 我们完全可以在代码中实现 但是当其他方法需要复用呢？ 以后需要修改的话都写在代码里面有没有可能会对其他代码产生影响呢？
 * 应该把这些一个个需要处理的当作独立的抽取出来  后面通过配置 可以选择哪些要哪些不要 哪些在前 哪些在后
 *
 * 责任链 本质是个线性结构 我们这里用链表的方式实现
 * 符合 单一职责原则  开闭原则 可以控制执行顺序
 * 将业务代码与责任校验解耦
 *
 * SpringSecurity 就是一套过滤器链安全框架 就是责任链设计模式 一个过滤器走完走下一个过滤器
 *
 */
public class ChainOfResponsibilityTest {
    public static void main(String[] args) {

        Request request = new Request(false,true,false,false,"xxx");
        Handler handler = new RequestIpHandler(new RequestLoginHandler(null));
        if (handler.process(request)) {
            System.out.println("执行正常业务操作");
        }else{
            System.out.println("访问异常");
        }

    }
}

//模拟请求对象
class Request{

    private boolean ipOk; //IP合法吗
    private boolean loggedOn; //登录与否
    private boolean isPermits; //身份是否合规
    private boolean containSensitiveWords; //有没有敏感词
    private String requestBody;

    public Request(boolean ipOk, boolean loggedOn, boolean isPermits, boolean containSensitiveWords, String requestBody) {
        this.ipOk = ipOk;
        this.loggedOn = loggedOn;
        this.isPermits = isPermits;
        this.containSensitiveWords = containSensitiveWords;
        this.requestBody = requestBody;
    }

    public boolean isIpOk() {
        return ipOk;
    }

    public void setIpOk(boolean ipOk) {
        this.ipOk = ipOk;
    }

    public boolean isLoggedOn() {
        return loggedOn;
    }

    public void setLoggedOn(boolean loggedOn) {
        this.loggedOn = loggedOn;
    }

    public boolean isPermits() {
        return isPermits;
    }

    public void setPermits(boolean permits) {
        isPermits = permits;
    }

    public boolean isContainSensitiveWords() {
        return containSensitiveWords;
    }

    public void setContainSensitiveWords(boolean containSensitiveWords) {
        this.containSensitiveWords = containSensitiveWords;
    }

    public String getRequestBody() {
        return requestBody;
    }

    public void setRequestBody(String requestBody) {
        this.requestBody = requestBody;
    }
}

//责任链上的每个节点模板
abstract class Handler{
    Handler next; //节点一个连着一个 没有后节点的节点肯定就是最后一个节点(责任链末端)了

    public Handler(Handler next) {
        this.next = next;
    }

    public Handler getNext() {
        return next;
    }

    public void setNext(Handler next) {
        this.next = next;
    }

    //具体责任节点处理逻辑
    abstract boolean process(Request request);

}


//IP责任节点
class RequestIpHandler extends Handler{

    //这个构造就可以实现当当前节点实现完成后要交给下一个什么节点来处理next如果为空就肯定是最后的节点了
    public RequestIpHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.println("IP是否合法责任控制");
        //如果当前IP校验通过
        if(request.isIpOk()){
            //调用下个责任节点去校验
            Handler next = getNext();
            //下个节点为Null 则代表当前节点是最后一个责任节点
            if(null == next){
                return true;
            }
            //执行下个节点的责任控制
            return next.process(request);
        }
        return false;
    }
}

//登录责任节点
class RequestLoginHandler extends Handler{

    public RequestLoginHandler(Handler next) {
        super(next);
    }

    @Override
    boolean process(Request request) {
        System.out.println("是否登录责任控制");
        if(request.isLoggedOn()){
            Handler next = getNext();
            if(null == next){
                return true;
            }
            return next.process(request);
        }
        return false;
    }
}








